library ieee;
 use ieee.std_logic_1164.all;
 use ieee.std_logic_unsigned.all;

library work;
 use work.router_pack.all;

-- synopsys translate_off
-- synthesis translate_off
--library csx_HRDLIB_FTSM;
-- use csx_HRDLIB_FTSM.VCOMPONENTS.all;
-- synthesis translate_on
-- synopsys translate_on


-------------------------------------------------------------------------------
entity spa8 is
-------------------------------------------------------------------------------
port( 
      RESET   : in  std_logic;
 
      -- MUTEX input i/f: --
      R       : in  std_logic_vector(num_of_vc_con*num_of_sl_con-1 downto 0);
      GATE    : in  std_logic;
      
      -- MUTEX output i/f: --
      G       : out std_logic_vector(num_of_vc_con*num_of_sl_con-1 downto 0);
       
      -- Data Latches: --
      L       : out std_logic_vector(num_of_vc_con*num_of_sl_con-1 downto 0)
);           
-------------------------------------------------------------------------------
end spa8 ;
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
architecture spa8_arch of spa8 is
-------------------------------------------------------------------------------
component mutex
port( 
      -- MUTEX input i/f: --
      R1      : in  std_logic;
      R2      : in  std_logic;

      -- MUTEX output i/f: --
      G1      : out std_logic;
      G2      : out std_logic
);           
end component;

component srlab2
port(
      RN                             :	in    std_logic;
      SN                             :	in    std_logic;
      Q                              :	out   std_logic;
      QN                             :	out   std_logic
);
end component;

component c_element
port( 
      -- Input i/f: --
      A     : in  std_logic;
      B     : in  std_logic;

      -- output i/f: --
      Q     : out std_logic
);           
end component;

signal g1_arr : std_logic_vector(num_of_vc_con*num_of_sl_con-1 downto 0);
signal g2_arr : std_logic_vector(num_of_vc_con*num_of_sl_con-1 downto 0);
signal g_and_arr : std_logic_vector(num_of_vc_con*num_of_sl_con-1 downto 0);

signal r_or_not, r_from_latch : std_logic; 

signal sig_high, sig_low :std_logic;

signal pri_mod_out : std_logic_vector(num_of_vc_con*num_of_sl_con-1 downto 0);

signal g_or_not : std_logic; 

 type ready_chan_type is array (0 to num_of_sl_con-1) of std_logic_vector(num_of_vc_con-1 downto 0);
 signal ready_chan : ready_chan_type;
 constant ready_chan_all_c : ready_chan_type := (others=>(others=>'1'));
begin

sig_high <= '1';
sig_low  <= '0';

r_or_not <= not ( R(0) or R(1) or R(2) or R(3) or R(4) or R(5) or R(6) or R(7) );

u_srlab2: srlab2 
port map( 
      RN    => g_or_not,
      SN    => r_or_not,

      Q     => r_from_latch, -- lock
      QN    => open
);   


sl_data_latch_gen: for i in 0 to (num_of_sl_con*num_of_vc_con-1) generate

 u_mutex_spa: mutex
 port map( 

      R1      => r_from_latch, -- lock
      R2      => R(i),

      G1      => g1_arr(i),
      G2      => g2_arr(i)
 );

 g_and_arr(i) <= g2_arr(i) and r_from_latch;  -- req + lock

 u_c_element1: c_element
 port map( 
      A     => g2_arr(i),
      B     => pri_mod_out(i),

      Q     => G(i)
 ); 

end generate;

-- Latch is open when request are valid and locked.
L <= not g_and_arr;

sl_ready_chan_gen: for i in 0 to (num_of_sl_con-1) generate
  vc_run_gen: for j in 0 to (num_of_vc_con-1) generate

      ready_chan(i)(j) <= g1_arr(2*i+j) xor g_and_arr(2*i+j);

  end generate;
end generate;

 -- Priority: --
 -- 0 SL1, VC2  -- LSB
 -- 1 SL1, VC1
 -- 2 SL2, VC2
 -- 3 SL2, VC1
 -- 4 SL3, VC2
 -- 5 SL3, VC1
 -- 6 SL4, VC2
 -- 7 SL4, VC1  -- MSB -- Arbitrary: VC1 has priority over VC2

 pri_mod_out(7) <= g_and_arr(7) when  (ready_chan=ready_chan_all_c) else '0';
 pri_mod_out(6) <= g_and_arr(6) when ((ready_chan=ready_chan_all_c) and (g_and_arr(7 downto 7)="0")) else '0';
 pri_mod_out(5) <= g_and_arr(5) when ((ready_chan=ready_chan_all_c) and (g_and_arr(7 downto 6)="00")) else '0';
 pri_mod_out(4) <= g_and_arr(4) when ((ready_chan=ready_chan_all_c) and (g_and_arr(7 downto 5)="000")) else '0';
 pri_mod_out(3) <= g_and_arr(3) when ((ready_chan=ready_chan_all_c) and (g_and_arr(7 downto 4)="0000")) else '0';
 pri_mod_out(2) <= g_and_arr(2) when ((ready_chan=ready_chan_all_c) and (g_and_arr(7 downto 3)="00000")) else '0';
 pri_mod_out(1) <= g_and_arr(1) when ((ready_chan=ready_chan_all_c) and (g_and_arr(7 downto 2)="000000")) else '0';
 pri_mod_out(0) <= g_and_arr(0) when ((ready_chan=ready_chan_all_c) and (g_and_arr(7 downto 1)="0000000")) else '0';

-- Gate: lock reset.
g_or_not <= not (GATE or RESET);

-------------------------------------------------------------------------------
end spa8_arch;
-------------------------------------------------------------------------------                 

   
-------------------------------------------------------------------------------
configuration  spa8_cfg  of spa8 is
-------------------------------------------------------------------------------
   for spa8_arch
   end for;
-------------------------------------------------------------------------------
end  spa8_cfg;              
-------------------------------------------------------------------------------
                 
